package it.uni.bo.monitoring.queue;

import static it.uni.bo.monitoring.service.StaticFields.CONTENT_MIN_SIZE;
import static it.uni.bo.monitoring.service.StaticFields.KEY_SIZE;
import static it.uni.bo.monitoring.service.StaticFields.QUERY_ALL_RAWDATA;
import static it.uni.bo.monitoring.service.StaticFields.QUERY_SQL_RAWDATA;

import it.uni.bo.monitoring.mapping.hibernate.RawData;
import it.uni.bo.monitoring.protocol.server.DataObject;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;


import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;



public class LazyInsertRawData  extends Thread {

	private BlockingQueue<byte[]> udpQueue;
	private BlockingQueue<DataObject> rawQueue;
	private SessionFactory factory;
	private Logger l;
	
	private static final String INFO_INSERT="inserisco in RawData i record";
	private static final String INFO_LOAD="carico in memoria i record";

	public LazyInsertRawData(BlockingQueue<byte[]> udpQueue, BlockingQueue<DataObject> rawQueue, SessionFactory factory) {
		l = Logger.getLogger(this.getClass());
		this.udpQueue=udpQueue;
		this.rawQueue=rawQueue;
		this.factory=factory;
		loadBackup();
	}

	public synchronized void run() {
		ArrayList<DataObject> doArray = new ArrayList<DataObject>();

		Session session = null;
		if(factory!=null)
			while(true){
				try {
					doArray.clear();
					int num=0;
					do{
						byte[] object=null;
						object =udpQueue.take();
						udpQueue.remove(object);
						if(object!=null){
							int minSize= KEY_SIZE + CONTENT_MIN_SIZE;
							if(object.length>=minSize){

								//recupero la chiave del pacchetto
								byte[] key = new byte[KEY_SIZE];
								for(int i=0;i<KEY_SIZE;i++)
									key[i]=object[i];

								//recupero il contenuto del pacchetto
								int contentSize = object.length-KEY_SIZE;
								byte[] content = new byte[contentSize];
								for(int i=KEY_SIZE;i<object.length;i++)
									content[i-KEY_SIZE]=object[i];


								if((session==null) || (!session.isOpen()))
									session=factory.openSession();
								doArray.add(new DataObject(key,content));

								Query query = session.createSQLQuery(QUERY_SQL_RAWDATA);
								query.setBinary(0, key);
								query.setBinary(1, content);
								//l.info("Hibernate: "+QUERY_SQL_RAWDATA+" --[ "+new String(key)+" "+new String(content)+" ]");
								query.executeUpdate();
								num++;
							}
						}
					}while(udpQueue.size()>0);
					//l.info(INFO_INSERT +" ("+num+")");
				}catch (InterruptedException e) {
					l.error(e.getMessage());
				}
				finally{
					if ((session!=null) && (session.isOpen())) 
						session.close(); 
					rawQueue.addAll(doArray);
				}
			}
	}
	
	private void loadBackup() {
		if(factory!=null){
			Session session = factory.openSession();
			Iterator<RawData> a = session.createQuery(QUERY_ALL_RAWDATA).iterate(); 
			//l.info("Hibernate: "+QUERY_ALL_RAWDATA);
			int num=0;

			while(a.hasNext()){
				RawData rd = a.next();
				num++;
				rawQueue.add(new DataObject(rd.getIdKey(),rd.getContent()));
			}
			if(num>0)
				l.info(INFO_LOAD +" ("+num+")");


			if ((session!=null) && (session.isOpen())) 
				session.close(); 

		}
	}
}
